#!/usr/bin/php -q
<?php
//	License for all code of this IssabelPBX module can be found in the license file inside the module directory
//	Copyright 2006-2014 Schmooze Com Inc.
//
date_default_timezone_set('America/Los_Angeles');
require_once ("libissabelpbx.install.php");
require_once(dirname(__FILE__) . '/amp_conf/htdocs/admin/libraries/php-upgrade.functions.php');
require_once(dirname(__FILE__) . '/amp_conf/htdocs/admin/libraries/sql.functions.php');
require_once(dirname(__FILE__) . '/amp_conf/htdocs/admin/libraries/utility.functions.php');

# constants
define("AMP_CONF", "/etc/amportal.conf");
define("ASTERISK_CONF", "/etc/asterisk/asterisk.conf");
define("UPGRADE_DIR", dirname(__FILE__)."/upgrades");
define("MODULE_DIR", dirname(__FILE__)."/amp_conf/htdocs/admin/modules/");

# semi constants
$webroot	= "/var/www/html";
$ampsbin_dir = "/usr/local/sbin";	// default if not set
$ampbin_dir = "/var/lib/asterisk/bin";
$asterisk_user	= "asteriskuser";
$asterisk_pass	= "amp109";

/********************************************************************************************************************/

function showHelp() {
	out("Optional parameters:",false);
	out("  --help, -h, -?           Show this help",false);
	out("  --dbhost <ip address>    Use a remote database server",false);
	out("  --dbname databasename    Use database name specified, instead of 'asterisk'",false);
	out("  --username <user>        Use <user> to connect to db and write config",false);
	out("  --password <pass>        Use <pass> to connect to db and write config",false);
	out("  --issabelpbxip <ip>         IssabelPBX web interface is accessed from <ip>",false);
	out("  --webroot <path>         Web root where IssabelPBX will be installed",false);
	out("  --cgibin <path>          Path where cgi-bin's lives",false);
	out("  --bin <path>             Path of asterisk binaries",false);
	out("  --sbin <path>            Path of system admin binaries",false);
	out("  --asteriskuser <user>    Asterisk Manager username",false);
	out("  --asteriskpass <pass>    Asterisk Manager password",false);
	out("  --asteriskip <ip>        Asterisk Manager IP address",false);
	out("  --debug                  Enable debug output",false);
	out("  --dry-run                Don't actually do anything",false);
	out("  --force-version <ver>    Force upgrade from version <ver>",false);
	out("  --skip-module-install    Don't run install scripts for packaged modules, the files are still loaded.",false);
	out("                           In a development environment you may not want the install scripts run.",false);
	out("  --no-files               Just run updates without installing files",false);
	out("  --force-overwrite        Don't ask if it is ok to overwrite modified files, assume yes for all.",false);
	out("  --install-moh            Install default music-on-hold files (normally doesn't, unless ",false);
	out("                           it's a new installation)",false);
	out("  --dev-links              Make links to files in the source directory instead of copying",false);
	out("                           (intended for developers only)",false);
	out("  --update-links           Update dev links without running through the whole install process (Bail before modules)", false);
	out("  --my-svn-is-correct      Ignore Asterisk version, assume it is correct",false);
	out("  --engine <name>          Use the specified PBX Engine ('asterisk')",false);
	out("  --uid <user>             Set ownership of files to user",false);
	out("  --gid <group>            Set ownership of files to group",false);
	out("  --scripted               Scripted install. Do not ask any questions.",false);
	out("                           (Intended for unattended installers only)",false);
	out("  --set-issabelpbx-settings   Force set the internal IssabelPBX DB Settings with install time parameters",false);
	out("  --installdb              Set up the IssabelPBX database",false);
	out("  --cleaninstall           Like 'make clean' will clean up any previous settings or previous setup while installing a-new",false);
	out("  --uninstall              Completely Uninstall IssabelPBX",false);
}

function install_parse_amportal_conf($filename) {
	$file = file($filename);
	foreach ($file as $line) {
		if (preg_match("/^\s*([a-zA-Z0-9]+)\s*=\s*(.*)\s*([;#].*)?/",$line,$matches)) {

			// TODO: force booleans into 0/1 this should be ok given the limited number of configuration values
			//
      switch (trim(strtolower($matches[2]))) {
      case 'false':
      case 'no':
      case 'off':
			case '0':
        $conf[$matches[1]] = '0';
			case 'true':
			case 'yes':
			case 'on':
			case '1':
        $conf[$matches[1]] = '1';
			default:
				$conf[$matches[1]] = $matches[2];
      break;
      }
		}
	}

	// use same defaults as function.inc.php
	if ( !isset($conf["AMPDBENGINE"]) || ($conf["AMPDBENGINE"] == "")) {
		$conf["AMPDBENGINE"] = "mysql";
	}

	if ( !isset($conf["AMPDBNAME"]) || ($conf["AMPDBNAME"] == "")) {
		$conf["AMPDBNAME"] = "asterisk";
	}

	if ( !isset($conf["AMPENGINE"]) || ($conf["AMPENGINE"] == "")) {
		$conf["AMPENGINE"] = "asterisk";
	}
	out("parsed amp_conf variables from $filename:");
	foreach ($conf as $keyword => $value) {
		out("amp_conf [$keyword] => [$value]");
	}

	return $conf;
}

function install_parse_asterisk_conf($filename) {
	$file = file($filename);
	foreach ($file as $line) {
		if (preg_match("/^\s*([a-zA-Z0-9]+)\s* => \s*(.*)\s*([;#].*)?/",$line,$matches)) {
			$conf[ $matches[1] ] = $matches[2];
		}
	}
	// Now set defaults if not set (although asterisk should fail if not set but at least
	// it will get the setup somewhat right
	//
	if (!isset($asterisk_conf['astetcdir']))    { $asterisk_conf['astetcdir']    = "/etc/asterisk"; }
	if (!isset($asterisk_conf['astmoddir']))    { $asterisk_conf['astmoddir']    = "/usr/lib/asterisk/modules"; }
	if (!isset($asterisk_conf['astvarlibdir'])) { $asterisk_conf['astvarlibdir'] = "/var/lib/asterisk"; }
	if (!isset($asterisk_conf['astagidir']))    { $asterisk_conf['astagidir']    = "/var/lib/asterisk/agi-bin"; }
	if (!isset($asterisk_conf['astspooldir']))  { $asterisk_conf['astspooldir']  = "/var/spool/asterisk"; }
	if (!isset($asterisk_conf['astrundir']))    { $asterisk_conf['astrundir']    = "/var/run/asterisk"; }
	if (!isset($asterisk_conf['astlogdir']))    { $asterisk_conf['astlogdir']    = "/var/log/asterisk"; }

	return $conf;
}

function write_amportal_conf($filename, $conf) {
	$file = file($filename);
	// parse through the file
	foreach (array_keys($file) as $key) {
		if (preg_match("/^\s*([a-zA-Z0-9]+)\s*=\s*(.*)\s*([;#].*)?/",$file[$key],$matches)) {
			// this is an option=value line
			if (isset($conf[ $matches[1] ])) {
				// rewrite the line, if we have this in $conf
				$file[$key] = $matches[1]."=".$conf[ $matches[1] ]."\n";
				// unset it so we know what's new
				unset($conf[ $matches[1] ]);
			}
		}
	}

	// add new entries
	foreach ($conf as $key=>$val) {
		$file[] = $key."=".$val."\n";
	}

	// write the file
	if (!$fd = fopen($filename, "w")) {
		fatal("Could not open ".$filename." for writing");
	}
	fwrite($fd, implode("",$file));
	fclose($fd);
}

function ask_overwrite($file1, $file2) {
	global $check_md5s;
	do {
		out($file2." has been changed from the original version.");
		outn("Overwrite (y=yes/a=all/n=no/d=diff/s=shell/x=exit)? ");
		$key = fgets(STDIN,1024);
		switch (strtolower($key[0])) {
			case "y": return true;
			case "a": $check_md5s=false; return true;
			case "n": return false;
			case "d":
				out("");
				// w = ignore whitespace, u = unified
				passthru("diff -wu ".escapeshellarg($file2)." ".escapeshellarg($file1));
			break;
			case "s":
				if (function_exists("pcntl_fork")) {
					out("");
					$shell = (isset($_ENV["SHELL"]) ? $_ENV["SHELL"] : "/bin/bash");
					out("Dropping to shell. Type 'exit' to return");
					out("-> Original file:  ".$file2);
					out("-> New file:       ".$file1);

					$pid = pcntl_fork();
					if ($pid == -1) {
						out("[ERROR] cannot fork");
					} else if ($pid) {
						// parent
						pcntl_waitpid($pid, $status);
						// we wait till the child exits/dies/whatever
					} else {
						pcntl_exec($shell, array(), $_ENV);
					}

					out("Returned from shell");
				} else {
					out("[ERROR] PHP not built with process control (--enable-pcntl) support: cannot spawn shell");
				}

			break;
			case "x":
				out("-> Original file:  ".$file2);
				out("-> New file:       ".$file1);
				out("Exiting install program.");
				exit(1);
			break;
		}
		out("");
	} while(1);
}

/** Write AMP-generated configuration files
 */
function generate_configs() {
	global $amp_conf;
	global $dryrun;
	global $debug;
	global $runas_uid;

	out("Generating Configurations.conf, (if Asterisk is not running, you will get an error");
	out("In case of error, start Asterisk and hit the red bar in the GUI to generate the Configurations.conf files");
	if (!$dryrun)
		// added --run-install to make it work like it has been working since retrieve_conf changed to not run module install scripts by default

		//
		// TODO: Should check if Asterisk is running and/or try to start it.
		//
		passthru("sudo -u $runas_uid ".trim($amp_conf["AMPBIN"])."/retrieve_conf --run-install --skip-registry-checks ".($debug ? ' --debug' : ''));
}


/** Collect AMP settings
 */
function collect_settings($filename, $dbhost = '', $dbuser = '', $dbpass = '', $dbname = 'asterisk') {
	global $webroot;
	global $ampsbin_dir;
	global $ampbin_dir;
	global $asterisk_user;
	global $asterisk_pass;
	global $scripted;
	global $issabelpbxip;
	global $asteriskip;
	global $runas_uid;
	global $runas_gid;
	global $asterisk_user;
	global $asterisk_pass;

	out("Creating new $filename");

	if ($scripted == true) {
		# Scripted install. Everything should have been set for us, don't ask questions.
		out("Scripted install. Accepting command line params.");
		$amp_conf["AMPDBUSER"] = $dbuser;
		$amp_conf["AMPDBPASS"] = $dbpass;
		$amp_conf["AMPDBHOST"] = $dbhost;
		$amp_conf["AMPDBNAME"] = $dbname;
		$amp_conf["AMPMGRUSER"] = $asterisk_user;
		$amp_conf["AMPMGRPASS"] = $asterisk_pass;
		$amp_conf["AMPWEBROOT"] = $webroot;
		$amp_conf["AMPWEBADDRESS"] = $issabelpbxip;
		$amp_conf["ASTMANAGERHOST"] = $asteriskip;
		$amp_conf["AMPEXTENSIONS"] = "extensions";
		$amp_conf["AMPBIN"] = $ampbin_dir;
		$amp_conf["AMPSBIN"] = "$ampsbin_dir";
		$amp_conf["AMPASTERISKWEBUSER"] = $runas_uid;
		$amp_conf["AMPASTERISKWEBGROUP"] = $runas_gid;
		$amp_conf["AMPASTERISKUSER"] = $runas_uid;
		$amp_conf["AMPASTERISKGROUP"] = $runas_gid;
		$amp_conf["AMPDEVUSER"] = $runas_uid;
		$amp_conf["AMPDEVGROUP"] = $runas_gid;
		write_amportal_conf($filename, $amp_conf);
		outn(AMP_CONF." written");
		return;
	}

	outn("Enter your USERNAME to connect to the '$dbname' database:\n [".($dbuser ? $dbuser : $asterisk_user) . "] ");
	$key = trim(fgets(STDIN,1024));
	if (preg_match('/^$/',$key))
		$amp_conf["AMPDBUSER"] = ($dbuser ? $dbuser : $asterisk_user);
	else
		$amp_conf["AMPDBUSER"] = $key;

	outn("Enter your PASSWORD to connect to the '$dbname' database:\n [".($dbpass ? $dbpass : $asterisk_pass)."] ");
	$key = trim(fgets(STDIN,1024));
	if (preg_match('/^$/',$key))
		$amp_conf["AMPDBPASS"] = ($dbpass ? $dbpass : $asterisk_pass);
	else
		$amp_conf["AMPDBPASS"] = $key;

	outn("Enter the hostname of the '$dbname' database:\n [".($dbhost ? $dbhost : "localhost")."] ");
	$key = trim(fgets(STDIN,1024));
	if (preg_match('/^$/',$key))
		$amp_conf["AMPDBHOST"] = ($dbhost ? $dbhost : "localhost");
	else
		$amp_conf["AMPDBHOST"] = $key;

	outn("Enter a USERNAME to connect to the Asterisk Manager interface:\n [admin] ");
	$key = trim(fgets(STDIN,1024));
	if (preg_match('/^$/',$key)) $amp_conf["AMPMGRUSER"] = "admin";
	else $amp_conf["AMPMGRUSER"] = $key;

	$rs = substr(md5(rand()), 0, 5);
	outn("Enter a PASSWORD to connect to the Asterisk Manager interface:\n [amp111] ");
	$key = trim(fgets(STDIN,1024));
	if (preg_match('/^$/',$key)) $amp_conf["AMPMGRPASS"] = 'amp111';
	else $amp_conf["AMPMGRPASS"] = $key;

	do {
		out("Enter the path to use for your AMP web root:\n [$webroot] ");
		$key = trim(fgets(STDIN,1024));
		if (preg_match('/^$/',$key))
			$amp_conf["AMPWEBROOT"] = "$webroot";
		else
			$amp_conf["AMPWEBROOT"] = rtrim($key,'/');

        $webroot = $amp_conf["AMPWEBROOT"];

		if (is_dir($amp_conf["AMPWEBROOT"])) {
			break;
		} else if (amp_mkdir($amp_conf["AMPWEBROOT"],"0755",true)){
			out("Created ".$amp_conf["AMPWEBROOT"]);
			break;
		} else {
			fatal("Cannot create ".$amp_conf["AMPWEBROOT"]."!");
		}
	} while(1);

	outn("Enter the IP ADDRESS or hostname used to access the AMP web-admin:\n [$issabelpbxip] ");
	$key = trim(fgets(STDIN,1024));
	if (preg_match('/^$/',$key)) $amp_conf["AMPWEBADDRESS"] = $issabelpbxip;
	else $amp_conf["AMPWEBADDRESS"] = $key;

	outn("Use simple Extensions [extensions] admin or separate Devices and Users [deviceanduser]?\n [extensions] ");
	$key = trim(fgets(STDIN,1024));
	if (preg_match('/^$/',$key)) $amp_conf["AMPEXTENSIONS"] = "extensions";
	else $amp_conf["AMPEXTENSIONS"] = $key;

	do {
		out("Enter directory in which to store AMP executable scripts:\n [$ampbin_dir] ");
		$key = trim(fgets(STDIN,1024));
		if (preg_match('/^$/',$key))
			$amp_conf["AMPBIN"] = $ampbin_dir;
		else
			$amp_conf["AMPBIN"] = rtrim($key,'/');

		if (is_dir($amp_conf["AMPBIN"])) {
			break;
		} else if (amp_mkdir($amp_conf["AMPBIN"],"0755",true)){
			out("Created ".$amp_conf["AMPBIN"]);
			break;
		} else {
			fatal("Cannot create ".$amp_conf["AMPBIN"]."!");
		}
	} while(1);

	do {
		out("Enter directory in which to store super-user scripts:\n [$ampsbin_dir] ");
		$key = trim(fgets(STDIN,1024));
		if (preg_match('/^$/',$key))
			$amp_conf["AMPSBIN"] = "$ampsbin_dir";
		else
			$amp_conf["AMPSBIN"] = rtrim($key,'/');

		if (is_dir($amp_conf["AMPSBIN"])) {
			break;
		} else if (amp_mkdir($amp_conf["AMPSBIN"],"0755",true)){
			out("Created ".$amp_conf["AMPSBIN"]);
			break;
		} else {
			fatal("Cannot create ".$amp_conf["AMPSBIN"]."!");
		}
	} while(1);

	// write amportal.conf
	write_amportal_conf($filename, $amp_conf);
	outn(AMP_CONF." written");
}

/** Set base of packaged modules to the versions packaged in the tarball since they are
 *  getting overwritten with the tarball from anything that may have been updated online.
 *
 */
function set_base_version() {
	global $dryrun;

	// read modules list from MODULE_DIR
	//
	$included_modules = array();
	$dir = opendir(MODULE_DIR);
	while ($file = readdir($dir)) {
		if ($file[0] != "." && $file[0] != "_" && is_dir(MODULE_DIR."/".$file)) {
			$included_modules[] = $file;
		}
	}
	closedir($dir);

	foreach ($included_modules as $up_module) {
		outn("Checking $up_module.. ");
		if (!$dryrun) {
			out(set_module_version($up_module));
		} else {
			out("Dry Run Not Updated");
		}
	}
}

/** Install all modules packaged with the install. We use the force flag because the
 *  the assumption is that the dependencies are met and the package is able to have
 *  the modules installed.
 */
function install_modules() {
	global $dryrun;
	global $amp_conf;

	// read modules list from MODULE_DIR
	//
	$included_modules = array();
	$dir = opendir(MODULE_DIR);
	while ($file = readdir($dir)) {
		if ($file[0] != "." && $file[0] != "_" && is_dir(MODULE_DIR."/".$file)) {
			$included_modules[] = $file;
		}
	}
	closedir($dir);

	$output = array();
	$keep_checking = true;
	$num_modules = false;
	while ($keep_checking && count($included_modules)) {
		if ($num_modules === count($included_modules)) {
			$keep_checking = false;
		} else {
			$num_modules = count($included_modules);
		}
		foreach ($included_modules as $id => $up_module) {
			outn("Checking $up_module.. ");
			if (!$dryrun) {
				// if $keep_checking then check dependencies first and skip if not met
				// otherwise we will install anyhow even if some dependencies are not met
				// since it is included. (TODO: should we not?)
				//
				if ($keep_checking) {
					exec($amp_conf['AMPBIN']."/module_admin --no-warnings checkdepends $up_module",$output,$retval);
					unset($output);
					if ($retval) {
						out("dependencies pending");
						continue;
					}
				}
				// Framework modules cannot be enabled, only installed.
				//
				switch ($up_module) {
				case 'framework':
				case 'fw_ari':
					system($amp_conf['AMPBIN']."/module_admin --no-warnings -f install $up_module");
					out("installed");
					break;
				default:
					system($amp_conf['AMPBIN']."/module_admin --no-warnings -f install $up_module");
					system($amp_conf['AMPBIN']."/module_admin --no-warnings -f enable $up_module");
					out("installed");
				}
				unset($included_modules[$id]);
			} else {
				out("Dry Run Not Installed");
			}
		}
  	}
}

/** Set the module version number to the packaged version and enable
 *  module must require not install.php or install.sql script
 *  this is primarily to package core and framework with IssabelPBX tarballs
 *
 */
function set_module_version($module) {
	global $db;

	$module_dir = MODULE_DIR;
	$file_path = $module_dir.$module."/module.xml";
	if (file_exists($file_path)) {
		// TODO: this is bad, there are other version tags (depends on) but this
		//       is equivalnet to what publish.pl does, so it expects this to be
		//       at the top.
		//
		$module_xml = file_get_contents($file_path);
		if (preg_match('/<version>(.+)<\/version>/', $module_xml, $matches)) {
			$version = $matches[1];
		} else {
			fatal("ERROR: $file_path found but no version information");
		}
	} else {
		return  "not packaged, no updating needed";
	}

	// If we didn't return above, then we found the package as part of the install
	// tarball and want to update the version info since this might be overwriting
	// an existing install that has a newer version.
	//
	$sql = "SELECT version FROM modules WHERE modulename = '$module'";
	$result = $db->getCol($sql);
	if(DB::IsError($result)) {
		fatal("error accessing version table: ".$result->getMessage());
	}
	$sql = "";
	if (count($result) == 0) {
		// insert but disable as we have to first run install scripts which come later
		$sql = "INSERT INTO modules (modulename, version, enabled) VALUES ('$module', '$version', 0)";
	} else if ($result[0] != $version) {
		if (version_compare_issabel($version, $result[0], "gt")) {
			// if new version is greater than old, then we disable the module and it will get enabled next when installed
			//
			$sql = "UPDATE modules SET version = '$version', enabled = 0 WHERE modulename = '$module'";
		} else {
			// if new version is equal to or less than old, then we leave it in the enable/disable state it was in but just
			// reset the version number.
			//
			$sql = "UPDATE modules SET version = '$version' WHERE modulename = '$module'";
		}
	}
	if ($sql) {
		debug($sql);
		$result = $db->query($sql);
		if(DB::IsError($result)) {
			fatal("error writing to version table: ".$result->getMessage());
		}
		return "updated to $version";
	} else {
		return "already at $version";
	}
}

function installampimport_mysql_dump($file,$db=NULL) {
    if(!isset($db)) {
        global $db;
    }

    $dir = dirname(__FILE__);
    if(file_exists($dir.'/SQL/'.$file)) {
        // Temporary variable, used to store current query
        $templine = '';
        // Read in entire file
        $lines = file($dir.'/SQL/'.$file);
        // Loop through each line
        foreach ($lines as $line)
        {
            // Skip it if it's a comment
            if (substr($line, 0, 2) == '--' || $line == '')
                continue;

            // Add this line to the current segment
            $templine .= $line;
            // If it has a semicolon at the end, it's the end of the query
            if (substr(trim($line), -1, 1) == ';')
            {
                // Perform the query
                $result = $db->query($templine);
        		if(DB::IsError($result)) {
        			fatal("Error performing query: ". $templine . " Message:".$result->getMessage());
        		}
                // Reset temp variable to empty
                $templine = '';
            }
        }
    }
}

/********************************************************************************************************************/

//
// TODO: will this work, basically using bootstrap once installed if using to upgrade, etc?
/*
$bootstrap_settings['skip_astman']) = true;
$bootstrap_settings['issabelpbx_auth'] = false;
$restrict_mods = true;
if (@include_once(getenv('ISSABELPBX_CONF') ? getenv('ISSABELPBX_CONF') : '/etc/issabelpbx.conf')) {
  out(_("IssabelPBX already installed, bootstrapping"));
} else if (@include_once('/etc/asterisk/issabelpbx.conf')) {
  out(_("IssabelPBX already installed, bootstrapping"));
} else {
  // all the initialization here instead
}
*/

// **** Make sure we have STDIN etc

// from  ben-php dot net at efros dot com   at  php.net/install.unix.commandline
if (version_compare(phpversion(),'4.3.0','<') || !defined("STDIN")) {
	define('STDIN',fopen("php://stdin","r"));
	define('STDOUT',fopen("php://stdout","r"));
	define('STDERR',fopen("php://stderr","r"));
	register_shutdown_function( create_function( '' , 'fclose(STDIN); fclose(STDOUT); fclose(STDERR); return true;' ) );
}

// **** Make sure we have PEAR's DB.php, and include it

outn("Checking for PEAR DB..");
if (! @ include('DB.php')) {
	out("FAILED");
	fatal("PEAR must be installed (requires DB.php). Include path: ".ini_get("include_path"));
}
out("OK");

// **** Make sure we have PEAR's GetOpts.php, and include it

outn("Checking for PEAR Console::Getopt..");
if (! @ include("Console/Getopt.php")) {
	out("FAILED");
	fatal("PEAR must be installed (requires Console/Getopt.php). Include path: ".ini_get("include_path"));
}
out("OK");

// **** Parse out command-line options
$shortopts = "h?u:p:";
$longopts = array(
	"asteriskip=",
	"asteriskpass=",
	"asteriskuser=",
	"bin=",
	"cgibin=",
	"cleaninstall",
	"dbhost=",
	"dbname=",
	"debug",
	"dev-links",
	"dry-run",
	"engine=",
	"fopwebroot=",
	"force-overwrite",
	"force-version=",
	"issabelpbxip=",
	"gid=",
	"help",
	"install-fop",
	"install-moh",
	"installdb",
	"make-links-devel",
	"my-svn-is-correct",
	"no-files",
	"password=",
	"sbin=",
	"scripted",
	"set-issabelpbx-settings",
	"skip-module-install",
	"uid=",
	"uninstall",
	"update-links",
	"username=",
	"webroot=",
);

$args = Console_Getopt::getopt(Console_Getopt::readPHPArgv(), $shortopts, $longopts);
if (is_object($args)) {
	// assume it's PEAR_ERROR
	out($args->message);
	exit(255);
}

$debug = false;
$dryrun = false;
$install_files = true;
$override_astvers = false;
$scripted = false;

$install_moh = false;
$make_links = false;
$update_links = false;
$module_install = true;
$set_issabelpbx_settings = false;

$installamp_clean = false;
$uninstallamp = false;
$installdb = false;

//initialize variables to avoid php notices
$dbhost = null;
$dbname = 'asterisk';
$new_username = null;
$new_password = null;

$runas_uid = "asterisk";
$runas_gid = "asterisk";
$issabelpbxip = "192.168.1.1";
$asteriskip = "localhost";

foreach ($args[0] as $arg) {
	switch ($arg[0]) {
		case "--help": case "h": case "?":
			showHelp();
			exit(10);
		break;
		case "--dry-run":
			out("Dry-run only, nothing will be changed");
			$dryrun = true;
		break;
		case "--debug":
			$debug = true;
			debug("Debug mode enabled");
		break;
		case "--username": case "u":
			out("Using username: ".$arg[1]);
			$new_username = $arg[1];
		break;
		case "--password": case "p":
			out("Using password: ".str_repeat("*",strlen($arg[1])));
			$new_password = $arg[1];
		break;
		case "--force-version":
			$version = $arg[1];
			out("Forcing upgrade from version ".$version);
		break;
		case "--dbhost":
			$dbhost = $arg[1];
			out("Using remote database server at ".$dbhost);
		break;
		case "--dbname":
			$dbname = $arg[1];
			out("Using database ".$dbname);
		break;
		case "--no-files":
			$install_files = false;
			out("Running upgrade only, without installing files.");
		break;
		case "--force-overwrite":
	    $check_md5s = false;
			out("Overwriting all files including modified ones.");
		break;
		case "--my-svn-is-correct":
			$override_astvers = true;
		break;
		case "--engine":
			if ($arg[1] != 'asterisk') {
				fatal('Currently only "asterisk" is supported as a PBX engine');
			}
			$pbx_engine = $arg[1];
		break;
		case "--install-moh":
			$install_moh = true;
		break;
		case "--set-issabelpbx-settings":
			$set_issabelpbx_settings = true;
		break;
		case "--fopwebroot":
		case "--install-fop":
			out("install-fop: depricated setting, does nothing.");
		break;
		case "--update-links":
			$update_links = true;
		case "--make-links-devel":
		case "--dev-links":
			$make_links = true;
		break;
		case "--skip-module-install":
			$module_install = false;
		break;
		case "--webroot":
			$webroot = $arg[1];
			out("Using Webroot at ".$webroot);
		break;
		case "--cgibin":
			$cgibin = $arg[1];
			out("Using CGI-BIN at ".$cgibin);
		break;
		case "--bin":
			$ampbin_dir = $arg[1];
			out("Using bin at ".$ampbin_dir);
		break;
		case "--sbin":
			$ampsbin_dir = $arg[1];
			out("Using sbin at ".$ampsbin_dir);
		break;
		case "--asteriskuser":
			$asterisk_user = $arg[1];
			out("Using Asterisk user ".$asterisk_user);
		break;
		case "--asteriskpass":
			$asterisk_pass = $arg[1];
			out("Using asteriskpass ".str_repeat("*",strlen($arg[1])));
		break;
		case "--uid":
			$runas_uid = $arg[1];
			out("Setting ownership (user) to ".$runas_uid);
		break;
		case "--gid":
			$runas_gid = $arg[1];
			out("Setting ownership (group) to ".$runas_gid);
		break;
		case "--scripted":
			$scripted = true;
			out("Unattended installation. No questions will be asked");
		break;
		case "--issabelpbxip":
			$issabelpbxip = $arg[1];
			out("Setting IP address of web interface to $issabelpbxip");
		break;
		case "--asteriskip":
			$asteriskip = $arg[1];
			out("Setting IP address of asterisk to $asteriskip");
		break;
		case "--cleaninstall":
            $installamp_clean = true;
        break;
        case "--uninstall":
            $uninstallamp = true;
        break;
        case "--installdb":
            $installdb = true;
        break;
	}
}

if($installamp_clean || $uninstallamp) {
    global $webroot;
	global $asterisk_user;
	global $asterisk_pass;

    $oldampconf = array();
    if(file_exists('/etc/amportal.conf')) {
        $amportalconf = file_get_contents('/etc/amportal.conf');
        if(preg_match('/AMPWEBROOT=(.*)/',$amportalconf,$matches)) {
            $oldampconf['AMPWEBROOT'] = $matches[1];
        }
        if(preg_match('/AMPDBENGINE=(.*)/',$amportalconf,$matches)) {
            $oldampconf['AMPDBENGINE'] = $matches[1];
        }
        if(preg_match('/AMPDBUSER=(.*)/',$amportalconf,$matches)) {
            $oldampconf['AMPDBUSER'] = $matches[1];
        }
        if(preg_match('/AMPDBPASS=(.*)/',$amportalconf,$matches)) {
            $oldampconf['AMPDBPASS'] = $matches[1];
        }
        if(preg_match('/AMPDBNAME=(.*)/',$amportalconf,$matches)) {
            $oldampconf['AMPDBNAME'] = $matches[1];
        }
        if(preg_match('/AMPDBHOST=(.*)/',$amportalconf,$matches)) {
            $oldampconf['AMPDBHOST'] = $matches[1];
        }
        if(preg_match('/AMPBIN=(.*)/',$amportalconf,$matches)) {
            $oldampconf['AMPBIN'] = $matches[1];
        }
        outn("Remove /etc/amportal.conf?:\n [y] ");
        $key = trim(fgets(STDIN,1024));
    	switch($key) {
    	    case "n":
    	    case "no":
    	    break;
    	    case "y":
    	    case "yes":
    	    default:
    	        outn("Removing /etc/amportal.conf.....");
                unlink('/etc/amportal.conf');
                out("Done!");
    	    break;
    	}
	}
	if(file_exists('/etc/issabelpbx.conf')) {
        outn("Remove /etc/issabelpbx.conf?:\n [y] ");
        $key = trim(fgets(STDIN,1024));
    	switch($key) {
    	    case "n":
    	    case "no":
    	    break;
    	    case "y":
    	    case "yes":
    	    default:
    	        outn("Removing /etc/issabelpbx.conf.....");
                unlink('/etc/issabelpbx.conf');
                out("Done!");
    	    break;
    	}
	}
	if(file_exists('/usr/local/sbin/amportal')) {
        outn("Remove /usr/local/sbin/amportal?:\n [y] ");
        $key = trim(fgets(STDIN,1024));
    	switch($key) {
    	    case "n":
    	    case "no":
    	    break;
    	    case "y":
    	    case "yes":
    	    default:
    	        outn("Removing /usr/local/sbin/amportal.....");
                unlink('/usr/local/sbin/amportal');
                out("Done!");
    	    break;
    	}
	}
	if(!empty($oldampconf['AMPBIN']) && file_exists($oldampconf['AMPBIN'])) {
        outn("Remove All IssabelPBX Tools in ".$oldampconf['AMPBIN']."?:\n [y] ");
        $key = trim(fgets(STDIN,1024));
        $files = array("archive_recordings","issabelpbx_engine", "gen_amp_conf.php", "libissabelpbx.confgen.php", "retrieve_conf", "issabelpbx-cron-scheduler.php", "issabelpbx_setting", "generate_hints.php", "module_admin", "retrieve_parse_amportal_conf.pl");
        foreach (glob($oldampconf['AMPBIN']."/*") as $filename) {
            if(is_link($filename)) {
                if(preg_match('/'.preg_quote($oldampconf['AMPWEBROOT'],'/').'/i',readlink($filename))) {
                    $files[] = basename($filename);
                }
            }
        }
        switch($key) {
    	    case "n":
    	    case "no":
    	    break;
    	    case "y":
    	    case "yes":
    	    default:
    	        foreach($files as $file) {
    	            if(file_exists($oldampconf['AMPBIN'].'/'.$file)) {
        	            outn("Removing ".$oldampconf['AMPBIN']."/".$file.".....");
                        unlink($oldampconf['AMPBIN'].'/'.$file);
                        out("Done!");
                    }
    	        }
    	    break;
    	}
	}
	if(!empty($oldampconf) && isset($oldampconf['AMPWEBROOT']) && file_exists($oldampconf['AMPWEBROOT'])) {
        outn("Remove ".$oldampconf['AMPWEBROOT']."?:\n [y] ");
        $key = trim(fgets(STDIN,1024));
    	switch($key) {
    	    case "n":
    	    case "no":
    	    break;
    	    case "y":
    	    case "yes":
    	    default:
    	        outn("Removing ".$oldampconf['AMPWEBROOT']."......");
                exec('rm -Rf '.$oldampconf['AMPWEBROOT']);
                out("Done!");
    	    break;
    	}
	}
	if(!$uninstallamp && !empty($oldampconf) && $oldampconf['AMPDBENGINE'] == 'mysql') {
        outn("Reinitalize & Reinstall IssabelPBX's Asterisk Database?:\n [y] ");
    	$key = trim(fgets(STDIN,1024));
    	switch($key) {
    	    case "n":
    	    case "no":
    	    break;
    	    case "y":
    	    case "yes":
    	    default:
    	        outn("Erasing Database...");
    	        $datasource = 'mysql://'.$oldampconf["AMPDBUSER"].':'.$oldampconf["AMPDBPASS"].'@'.$oldampconf["AMPDBHOST"].'/'.$oldampconf["AMPDBNAME"];
        		$cleandb = DB::connect($datasource); // attempt connection

        		if(DB::IsError($cleandb)) {
                	out("FAILED");
                	fatal("Try not selecting 'y' on Reinitalize & Reinstall IssabelPBX's Asterisk Database");
                } else {
        	        $sql = "SHOW TABLES FROM ".$oldampconf['AMPDBNAME'];
        	        $tables = $cleandb->getAll($sql);
        	        foreach($tables as $list) {
        	            $sql = "DROP TABLE ".$oldampconf['AMPDBNAME'].".".$list[0];
        	            $cleandb->query($sql);
        	        }
        	        out("Done");
        	        outn("Reinstalling DB Structure...");
        	        installampimport_mysql_dump('newinstall.sql',$cleandb);
        	        out("Done");
                }
    	    break;
    	}
    }
	if($uninstallamp && (!empty($oldampconf) || !empty($new_username))) {
	    outn("Uninstall IssabelPBX's Asterisk Database?:\n [y] ");
		$u_username = !empty($oldampconf["AMPDBUSER"]) ? $oldampconf["AMPDBUSER"] : $new_username;
		$u_password = !empty($oldampconf["AMPDBPASS"]) ? $oldampconf["AMPDBPASS"] : (!empty($new_password) ? $new_password : '');
		$u_host = !empty($oldampconf["AMPDBHOST"]) ? $oldampconf["AMPDBHOST"] : (!empty($dbhost) ? $dbhost : 'localhost');
		$u_database = !empty($oldampconf["AMPDBNAME"]) ? $oldampconf["AMPDBNAME"] : (!empty($dbname) ? $dbname : 'asterisk');
    	$key = trim(fgets(STDIN,1024));
    	switch($key) {
    	    case "n":
    	    case "no":
    	    break;
    	    case "y":
    	    case "yes":
    	    default:
    	        outn("Erasing Database...");
    	        $datasource = 'mysql://'.$u_username.':'.$u_password.'@'.$u_host.'/'.$u_database;
        		$cleandb = DB::connect($datasource); // attempt connection

        		if(DB::IsError($cleandb)) {
                	out("FAILED");
                	fatal("Could Not Connect to Database (Probably already deleted)");
                } else {
        	        $sql = "SHOW TABLES FROM ".$u_database;
        	        $tables = $cleandb->getAll($sql);
        	        foreach($tables as $list) {
        	            $sql = "DROP TABLE ".$u_database.".".$list[0];
        	            $cleandb->query($sql);
        	        }
        	        out("Done");
                }
    	    break;
    	}
	}
	if($uninstallamp) {
	    die("Successfully Uninstalled IssabelPBX\n");
	}
}

// **** Look for user = root

// TODO: if we bootstrap, do this first before even trying. Also, is their a problem boostraping as user root???
//
outn("Checking user..");
//$current_user=(isset($_ENV["USER"]) ? $_ENV["USER"] : exec('whoami',$output));
$euid = (posix_getpwuid(posix_geteuid()));
$current_user = $euid['name'];
if ($current_user != "root"){
	out("FAILED");
	fatal($argv[0]." must be run as root");
}
out("OK");


// TODO: if we bootstrap, do this first before even trying.
//
outn("Checking if Asterisk is running..");
exec("pidof asterisk", $pid_val, $ret);
if ($ret) {
	out("FAILED");
	fatal($argv[0]."\n\tAsterisk must be running. If this is a first time install, you should start\n\tAsterisk by typing './start_asterisk start'\n\tFor upgrading, you should run 'amportal start'");
}
out("running with PID: ".$pid_val[0]."..OK");

// **** Check for amportal.conf, create if necessary

// TODO: Check if issabelpbx_settings has been setup, if so then we don't even want to mess with ampportal.conf, that
//       should only be first time install.
//
outn("Checking for ".AMP_CONF."..");
if (!file_exists(AMP_CONF)) {
	out(AMP_CONF." does not exist, copying default");
	copy("amportal.conf", AMP_CONF);

	// this file contains password and should not be a+r
	// this addresses http://issabel.org/trac/ticket/1878
	chown(AMP_CONF, $runas_uid);
	chgrp(AMP_CONF, $runas_gid);
	chmod(AMP_CONF, 0640);

	collect_settings(AMP_CONF, $dbhost, $new_username, $new_password, $dbname);

	out("Assuming new install, --install-moh added to command line");
	$install_moh = true;
}
out("OK");

// **** read amportal.conf

// TODO: see comments above, have we already boostraped, if so, skip this?
//
outn("Reading ".AMP_CONF."..");
$amp_conf = install_parse_amportal_conf(AMP_CONF);
if (count($amp_conf) == 0) {
	fatal("FAILED");
}
out("OK");

// TODO: if we boostrapped I think we can count on ALL of these being set but maybe it's
//       fine to do a sanity check?
//
// Ensure our "critical" variables are set.  We absolutely need these to copy in files.

if (!array_key_exists("AMPWEBROOT",$amp_conf)) {
	out("Adding AMPWEBROOT option to amportal.conf - using AMP default");
	$amp_conf["AMPWEBROOT"] = "/var/www/html";
}
if (!array_key_exists("AMPBIN",$amp_conf)) {
	out("Adding AMPBIN option to amportal.conf - using AMP default");
	$amp_conf["AMPBIN"] = "/var/lib/asterisk/bin";
}
if (!array_key_exists("AMPSBIN",$amp_conf)) {
	out("Adding AMPSBIN option to amportal.conf - using AMP default");
	$amp_conf["AMPSBIN"] = "/usr/sbin";
}
if (!array_key_exists("AMPDBENGINE",$amp_conf)) {
	out("Adding AMPDBENGINE option to amportal.conf - using AMP default");
	$amp_conf["AMPDBENGINE"] = "mysql";
}
if (!array_key_exists("AMPDBNAME",$amp_conf)) {
	out("Adding AMPDBNAME option to amportal.conf - using AMP default");
	$amp_conf["AMPDBNAME"] = "asterisk";
}

// TODO: if we boostrapped do we ignore these? (Can they even be set?)
//
if (isset($new_username)) {
	$amp_conf["AMPDBUSER"] = $new_username;
}
if (isset($new_password)) {
	$amp_conf["AMPDBPASS"] = $new_password;
}
if (isset($dbhost)) {
	$amp_conf["AMPDBHOST"] = $dbhost;
}
if (isset($dbname)) {
	$amp_conf["AMPDBNAME"] = $dbname;
}
// If they pre-set this in their amportal.conf or this is an upgrade, we should honor it as well
//
// TODO: if we boostrap, then this value could be normalized (1/0 I think?)
//
// write amportal.conf
// TODO: if we boostrapped we don't want to write amportal.conf, or do we? e.g. if we are running out of the file vs. the
//       database then we probably want to write, though there should be a issabelpbx_conf class to use that does that and knows
//       how to make that decsion as well as what to write?
//
write_amportal_conf(AMP_CONF, $amp_conf);

// **** Check for amportal.conf, create if necessary

outn("Checking for ".ASTERISK_CONF."..");
if (!file_exists(ASTERISK_CONF)) {
	out(ASTERISK_CONF." does not exist, copying default");
	copy("asterisk.conf", ASTERISK_CONF);
}
out("OK");

// **** read asterisk.conf

// TODO: if we boostrapped don't do this
//
outn("Reading ".ASTERISK_CONF."..");
$asterisk_conf = install_parse_asterisk_conf(ASTERISK_CONF);
if (count($asterisk_conf) == 0) {
	fatal("FAILED. Have you installed Asterisk?");
}
out("OK");

/* TODO: if we boostrapped this should have been done but doesn't hurt?
 */
if (isset($asterisk_conf['astetcdir'])) { $amp_conf['ASTETCDIR'] = $asterisk_conf['astetcdir']; }
if (isset($asterisk_conf['astmoddir'])) { $amp_conf['ASTMODDIR'] = $asterisk_conf['astmoddir']; }
if (isset($asterisk_conf['astvarlibdir'])) { $amp_conf['ASTVARLIBDIR'] = $asterisk_conf['astvarlibdir']; }
if (isset($asterisk_conf['astagidir'])) { $amp_conf['ASTAGIDIR'] = $asterisk_conf['astagidir']; }
if (isset($asterisk_conf['astspooldir'])) { $amp_conf['ASTSPOOLDIR'] = $asterisk_conf['astspooldir']; }
if (isset($asterisk_conf['astrundir'])) { $amp_conf['ASTRUNDIR'] = $asterisk_conf['astrundir']; }
if (isset($asterisk_conf['astlogdir'])) { $amp_conf['ASTLOGDIR'] = $asterisk_conf['astlogdir']; }

if (!isset($pbx_engine)) { $pbx_engine='asterisk'; }
out("Using $pbx_engine as PBX Engine");
$amp_conf["AMPENGINE"]=$pbx_engine;

// TODO: I guess we have new variables set, of course see note above if we boostrapped. Probably
//       this one stays?
//
write_amportal_conf(AMP_CONF, $amp_conf);


// **** Write asterisk version to ASTETCDIR/version

// TODO: does anything use this? What's the point? (other than we need the version for below)
//
$tmpoutput = '';
$tmpout = exec("asterisk -V", $tmpoutput, $exitcode);
if ($exitcode != 0) {
	fatal("Error executing asterisk: be sure Asterisk is installed and in the path");
}
if (!$fd = fopen($amp_conf['ASTETCDIR'].'/version','w')) {
	fatal('Cannot open '.$amp_conf['ASTETCDIR'].'/version for writing');
}
fwrite($fd, $tmpout);
fclose($fd);
// change to read-only
chmod($amp_conf['ASTETCDIR'].'/version',0444);


// normally this would be the contents of ASTETCDIR/version, but this is for simplicity, as we just read it above
$verinfo = $tmpout;

// **** Check asterisk version
//  Set the 'engine' to be 'asterisk14' if using asterisk 1.4, otherwise
//  'asterisk'
outn("Checking for Asterisk version..");
if ((preg_match('/^Asterisk (\d+(\.\d+)*)(-?(.*))$/', $verinfo, $matches)) ||
    (preg_match('/^Asterisk SVN-(\d+(\.\d+)*)(-?(.*))$/', $verinfo, $matches))) {
	if ((version_compare($matches[1], "1.6") < 0)) {
		fatal("Asterisk 1.6, 1.8 or 10 is required for this version of IssabelPBX. Detected version is: ".$matches[1]);
	}
	if (version_compare($matches[1], "14", "ge")) {
		fatal("Asterisk 1.6, 1.8, 10, 11, 12 or 13 is required for this version of IssabelPBX. Detected version is: ".$matches[1]);
	}
	out("{$matches[1]}");
  $asterisk_version = $matches[1];

} elseif (preg_match('/^Asterisk ([ABC]\.\d+(\.\d+)*)(-?(.*))$/', $verinfo, $matches)) {
	if (substr($matches[1], 0, 1) == "A") {
		fatal("Asterisk Business Edition B or C is required for this version of IssabelPBX. Detected version is: ".$matches[1]);
	}
	out("{$matches[1]}");
  $asterisk_version = '1.4'; //Not really, but this makes sure that proper execution occurs later on reload commands, etc.

} elseif ($asterisk_version = preg_match('/^Asterisk SVN.+/', $verinfo)) {
	out("FAIL");
	out("*** WARNING ***");
	out("You are not using a released version of Asterisk. We are unable to verify");
	out("that your Asterisk version is compatible with IssabelPBX. Whilst this probably");
	out("won't cause any problems, YOU NEED TO BE CERTAIN that it is compatible");
	out("with at least the released Asterisk version 1.2" );
	if ($override_astvers==false) {
		out("If you are SURE that this is compatible, you can re-run ".$argv[0]." with");
		out("the parameter --my-svn-is-correct");
		exit;
	} else {
		out("--my-svn-is-correct specified, continuing");
	}
} else {
	fatal("Could not determine asterisk version (got: \"".$verinfo."\" please report this)");
}

// **** Make sure selinux isn't enabled

outn("Checking for selinux..");
$tmpoutput = array();
$tmpout = exec("getenforce 2>/dev/null", $tmpoutput, $sereturn);
if (isset($tmpoutput[0]) && strtolower($tmpoutput[0]) === "enabled") {
        // this method seems better because disabled and permissive are the same
        // if a user installs and realizes selinux is running the other method
        // requires a reboot to get selinuxenabled to work after editing the  selinux config
        // this will allow you to use setenforce 0 which turns selinux into permissive mode which
        // doesnt enforce, it just warns.
	fatal("selinux is ENABLED. This is not supported. Please disable selinux before using IssabelPBX");
}
out("OK");

// **** Connect to database

// TODO: if we bootstrapped, we are already connected and this can all be skipped
//
outn("Connecting to database..");

$db_engine = $amp_conf["AMPDBENGINE"];
if ($db_engine != "sqlite3") {
	$db_user = $amp_conf["AMPDBUSER"];
	$db_pass = $amp_conf["AMPDBPASS"];
	$db_host = $amp_conf["AMPDBHOST"];
}
$db_name = $amp_conf["AMPDBNAME"];

// we still support older configurations,  and fall back
// into mysql when no other engine is defined
if ($db_engine == "")
{
	$db_engine = "mysql";
}

switch ($db_engine)
{
	case "pgsql":
	case "mysql":
		// datasource in in this style: dbengine://username:password@host/database
		if (!function_exists($db_engine.'_connect')) {
			out("FAILED");
			fatal($db_engine." PHP libraries not installed");
		}

		$datasource = $db_engine.'://'.$db_user.':'.$db_pass.'@'.$db_host.'/'.$db_name;
		$db = DB::connect($datasource); // attempt connection
		break;

	case "sqlite":
		die_issabelpbx("SQLite2 support is deprecated. Please use sqlite3 only.");
		break;

	case "sqlite3":
		if (!isset($amp_conf["AMPDBFILE"]))
			die("You must setup properly AMPDBFILE in /etc/amportal.conf");

		if (isset($amp_conf["AMPDBFILE"]) == "")
			die("AMPDBFILE in /etc/amportal.conf cannot be blank");

		/* on centos this extension is not loaded by default */
		if (! extension_loaded('sqlite3.so')  && ! extension_loaded('SQLITE3'))
			dl('sqlite3.so');

		if (! @require_once('DB/sqlite3.php') )
		{
			out("FAILED");
			fatal( "Your PHP installation has no PEAR/SQLite3 support. Please install php-sqlite3 and php-pear.");
		}

		$datasource = "sqlite3:///" . $amp_conf["AMPDBFILE"] . "?mode=0666";
		$db = DB::connect($datasource);
		break;

	default:
		die( "Unknown SQL engine: [$db_engine]");
}

if(DB::IsError($db)) {
	out("FAILED");
	debug($db->userinfo);
	out("Try running ".$argv[0]." --username=user --password=pass  (using your own user and pass)");
	fatal("Cannot connect to database");

}
out("OK");

if($installdb) {
    outn("Checking state of IssabelPBX DB...");
    $sql = "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '".$amp_conf["AMPDBNAME"]."'";
    if(!$db->getOne($sql)) {
        outn("IssabelPBX DB is empty, inserting standard rows...");
        installampimport_mysql_dump('newinstall.sql');
        out("Done!");
    } else {
        out("IssabelPBX DB is already populated skipping");
    }
}

// **** Read DB for version info

if (!isset($version)) {
	outn("Checking current version of AMP..");
	$version = install_getversion();
	if (!$version) {
		out("no version information");
		out("Assuming new installation");
	} else {
		out($version);
	}
}

// Check if issabelpbx_settings is there and has been initialized
// if it has anything less than about 5 settings in it (and that
// is probably quite low) then something is wrong so assume it
// is not there.
//
$sql = "SELECT count(*) FROM issabelpbx_settings";
$num_settings = $db->getOne($sql);
$force_amportal_conf = DB::IsError($num_settings) || $num_settings < 5;

// **** Copy files

if ($install_files)
{
    $asteriskuser = isset($amp_conf['AMPASTERISKUSER']) && $amp_conf['AMPASTERISKUSER'] ? $amp_conf['AMPASTERISKUSER'] : 'asterisk';
	outn("Installing new IssabelPBX files..");
	$check_md5s=true;
	$md5sums = read_md5_file(UPGRADE_DIR."/".$version.".md5");
	list($num_files, $num_copied) = recursive_copy("amp_conf", "", $md5sums);
    if(!file_exists(dirname(__FILE__).'/amp_conf/htdocs/admin/modules/_cache')) {
        mkdir(dirname(__FILE__).'/amp_conf/htdocs/admin/modules/_cache',0777,true);
        chown(dirname(__FILE__).'/amp_conf/htdocs/admin/modules',$asteriskuser);
        if(!file_exists(dirname(__FILE__).'/amp_conf/htdocs/admin/modules')) {
            die("We were not able to create the local modules directory, which is important\n");
        }
    }
	if(!file_exists($amp_conf['AMPWEBROOT'].'/admin/modules/_cache')) {
		mkdir($amp_conf['AMPWEBROOT'].'/admin/modules/_cache',0777,true);
		chown($amp_conf['AMPWEBROOT'].'/admin/modules',$asteriskuser);
		if(!file_exists($amp_conf['AMPWEBROOT'].'/admin/modules')) {
			die("We were not able to create the web modules directory, which is important\n");
		}
	}
    if (!is_file("/etc/asterisk/voicemail.conf")) {  
        copy("/etc/asterisk/voicemail.conf.template","/etc/asterisk/voicemail.conf"); 
    } else {  
        exec("grep vm_email /etc/asterisk/voicemail.conf", $output, $return);
        if($return==1) {
            if(is_file("/etc/asterisk/voicemail.conf.template")) {
                unlink("/etc/asterisk/voicemail.conf");
                copy("/etc/asterisk/voicemail.conf.template","/etc/asterisk/voicemail.conf"); 
            }
        }
    }
	if (!is_dir("/var/spool/asterisk/voicemail/device")) amp_mkdir("/var/spool/asterisk/voicemail/device", "0755", true);
	out("OK (".$num_copied." files copied, ".($num_files-$num_copied)." skipped)");

  // link the packed js library for ARI, if there the error will indicate that
  $libissabelpbx = $amp_conf['AMPWEBROOT'].'/admin/common/libissabelpbx.javascripts.js';
  $dest_libissabelpbx = $amp_conf['AMPWEBROOT'].'/recordings/theme/js/libissabelpbx.javascripts.js';
  if (!file_exists($amp_conf['AMPWEBROOT'].'/recordings/theme/js')) {
	mkdir($amp_conf['AMPWEBROOT'].'/recordings/theme/js',0755, true);
  }
  if (file_exists($libissabelpbx) && !file_exists($dest_libissabelpbx)) {
    outn(_("linking libissabelpbx.javascripts.js to theme/js.."));
    if (link($libissabelpbx, $dest_libissabelpbx)) {
      out(_("ok"));
    } else {
      out(_("possible error - check warning message"));
    }
  }
}

if (!$dryrun) {
  $asteriskuser = isset($amp_conf['AMPASTERISKUSER']) && $amp_conf['AMPASTERISKUSER'] ? $amp_conf['AMPASTERISKUSER'] : 'asterisk';

	if (file_exists($amp_conf["AMPSBIN"]."/amportal")) {
		exec("chmod 755 ".$amp_conf["AMPSBIN"]."/amportal");
		outn("amportal..");
	} else {
		outn("no amportal..");
	}
	if (file_exists($amp_conf["AMPSBIN"]."/fpbx")) {
		exec("chmod 755 ".$amp_conf["AMPSBIN"]."/fpbx");
		outn("fpbx..");
	} else {
		outn("no fpbx..");
	}
	if (file_exists($amp_conf["AMPBIN"]."/issabelpbx_engine")) {
		exec("chmod 755 ".$amp_conf["AMPBIN"]."/issabelpbx_engine");
		outn("issabelpbx_engine..");
	} else {
		outn("no issabelpbx_engine..");
	}
	if (file_exists($amp_conf["AMPBIN"]."/issabelpbx_setting")) {
		exec("chmod 755 ".$amp_conf["AMPBIN"]."/issabelpbx_setting");
		outn("issabelpbx_setting..");
	} else {
		outn("no issabelpbx_setting..");
	}
	if (file_exists($amp_conf["AMPBIN"]."/gen_amp_conf.php")) {
		exec("chmod 755 ".$amp_conf["AMPBIN"]."/gen_amp_conf.php");
		outn("gen_amp_conf.php..");
	} else {
		outn("no gen_amp_conf..");
	}
	out("done");

	// Ensure UIDs are set correctly before any chowns happen
	// Note - issabelpbx_engine must be used the first time to ensure that issabelpbx.conf exists.
	exec($amp_conf["AMPBIN"]."/issabelpbx_engine admin issabelpbx_setting AMPASTERISKWEBGROUP $runas_gid");
	exec($amp_conf["AMPBIN"]."/issabelpbx_setting AMPASTERISKWEBUSER $runas_uid");
	exec($amp_conf["AMPBIN"]."/issabelpbx_setting AMPASTERISKGROUP $runas_gid");
	exec($amp_conf["AMPBIN"]."/issabelpbx_setting AMPASTERISKUSER $runas_uid");
	exec($amp_conf["AMPBIN"]."/issabelpbx_setting AMPDEVGROUP $runas_gid");
	exec($amp_conf["AMPBIN"]."/issabelpbx_setting AMPDEVUSER $runas_uid");
	exec($amp_conf["AMPBIN"]."/issabelpbx_setting ASTMANAGERHOST $asteriskip");
	// edit conf file passwords and then
	// reload manager in asterisk if it is running:
	//
	if (file_exists(dirname(__FILE__)."/apply_conf.sh")) {
		out("apply username/password changes to conf files:");
		debug("Running ".dirname(__FILE__)."/apply_conf.sh");
		$apply_conf_out = array();
    if ($force_amportal_conf) {
			out("running apply_conf.sh from " . AMP_CONF);
      putenv('FORCE_AMPORTAL_CONF=1');
		  exec(dirname(__FILE__)."/apply_conf.sh ".AMP_CONF, $apply_conf_out);
      putenv('FORCE_AMPORTAL_CONF=');
    } else {
			out("running apply_conf.sh from issabelpbx_settings");
		  exec(dirname(__FILE__)."/apply_conf.sh", $apply_conf_out);
    }
		foreach ($apply_conf_out as $line) {
			out($line);
		}
		unset($apply_conf_out);
		out("done with apply_conf.sh");
	}

	/* As of Asterisk 1.4.16 or there about, a missing #include file will make the reload fail. So
   	we need to make sure that we have such for everything that is in our configs. We will simply
	 	look for the #include statements and touch the files vs. trying to inventory everything we may
	 	need and then forgetting something.
	*/

	outn("creating missing #include files..");
	$include_err = false;
	exec("grep '#include' ".$amp_conf['ASTETCDIR']."/*.conf | sed 's/;.*//; s/#include//'",$output,$retcode);
	if ($retcode != 0) {
		out("Error code $retcode: trying to search for missing #include files");
		$include_err = true;
	}

	foreach($output as $file) {
		if (trim($file) == '') {
			continue;
		}
		$parse1 = explode(':',$file);
		$parse2 = explode(';',$parse1[1]);
		$rawfile = trim($parse2[0]);
		if ($rawfile == '') {
			continue;
		}

		$target = ($rawfile[0] == '/') ? $rawfile : $amp_conf['ASTETCDIR']."/$rawfile";

		if (!file_exists($target)) {
			exec("sudo -u $asteriskuser touch $target", $output, $retcode);
				if ($retcode != 0) {
				out("Error code $retcode: trying to create empty file $target");
				$include_err = true;
			}
		}
	}
	if (! $include_err) {
		out("OK");
	}
	// reload manager in asterisk if it was running:
	//
  if (version_compare($asterisk_version,'1.4','ge')) {
	  system("asterisk -rx 'module reload manager'");
  } else {
	  system("asterisk -rx 'reload manager'"); //1.2 syntax
  }
}
out("OK");

// **** Create spool directories for monitor and fax
if (!is_dir($amp_conf["ASTSPOOLDIR"]."/monitor"))
	amp_mkdir($amp_conf["ASTSPOOLDIR"]."/monitor","0766",true);
if (!is_dir($amp_conf["ASTSPOOLDIR"]."/fax"))
	amp_mkdir($amp_conf["ASTSPOOLDIR"]."/fax","0766",true);

//Check to make sure database is installed
$sql = "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '".$amp_conf["AMPDBNAME"]."'";
if(!$db->getOne($sql)) {
    fatal('The '. $amp_conf["AMPDBNAME"] . ' ' . $amp_conf["AMPDBENGINE"] . ' database appears empty, try running with the "--cleaninstall --installdb" commands or install the database manually');
}
// **** Set permissions all files

// tell amportal/issabelpbx_engine to use amportal.conf and not bootstrap
// if issabelpbx_settings has not been setup yet or you will get an error.
//
if ($install_files)
{
	outn("Setting permissions on files..");
	if (!$dryrun) {
    if ($force_amportal_conf) {
      putenv('FORCE_AMPORTAL_CONF=1');
    }
		exec($amp_conf["AMPSBIN"]."/amportal chown");
    if ($force_amportal_conf) {
      putenv('FORCE_AMPORTAL_CONF=');
    }
	}
	out("OK");
}

// Run through all the upgrade scripts starting at the specified version
//
upgrade_all($version);

// Save $amp_conf variables so we can set the configured values
if (($set_issabelpbx_settings && $force_amportal_conf) || (!file_exists('/etc/redhat-release')))  {
	$amp_conf_file = $amp_conf;
}
outn("Creating or updating issabelpbx_conf settings..");
issabelpbx_settings_init(true);
out("..OK");

// TODO: if file is $force_amportal_conf let's go set any settings in issabelpbx_settings,
//       question is, should we do this further up???
//
if (($set_issabelpbx_settings && $force_amportal_conf) || (!file_exists('/etc/redhat-release'))) {
	out("Setting issabelpbx settings form " . AMP_CONF);
	$issabelpbx_conf =& issabelpbx_conf::create();
	foreach ($amp_conf_file as $keyword => $value) {
		if ($issabelpbx_conf->conf_setting_exists($keyword)) {
			$issabelpbx_conf->set_conf_values(array($keyword => $value),true,true);
			out("issabelpbx setting [$keyword] set to [$value]");
		} else {
			out("issabelpbx setting [$keyword] DOES NOT EXIST, can't set to [$value]");
		}
	}
} else {
    //We are here mainly because of bug #6159
    //Meaning they are installing this on CentOS manually so the above checks fail
    global $webroot;
    if(isset($webroot) && !empty($webroot) && ($webroot != $amp_conf['AMPWEBROOT'])) {
        $issabelpbx_conf =& issabelpbx_conf::create();
        outn("Noticed Irregular AMPWEBROOT setting....");
        if ($issabelpbx_conf->conf_setting_exists('AMPWEBROOT')) {
			$issabelpbx_conf->set_conf_values(array('AMPWEBROOT' => $webroot),true,true);
		}
        $amportalconf = file_get_contents('/etc/amportal.conf');
        $amportalconf = preg_replace('/AMPWEBROOT=.*/', 'AMPWEBROOT='.$webroot, $amportalconf);
        file_put_contents('/etc/amportal.conf',$amportalconf);
		out("Fixed");
    }
}

// **** Generate AMP configs
out("Generating AMP configs..");
generate_configs();
out("Generating AMP configs..OK");

$version = install_getversion();

// Now force an install for all modules that are packaged with the tarball
// directory.
//
if ($module_install && !$update_links) {
	install_modules();
} else {
	out("bypassing packaged module installation because --skip-module-install or --update-links flag");
}

if($update_links) {
	//copy framework into installed folder if it doesnt already exist
	if(!file_exists($amp_conf['AMPWEBROOT'].'/admin/modules/framework')) {
		mkdir($amp_conf['AMPWEBROOT'].'/admin/modules/framework');
	}
	copy(__DIR__.'/module.xml',$amp_conf['AMPWEBROOT'].'/admin/modules/framework/module.xml');
}


// **** Set reload flag for AMP admin
needreload();

if ($amp_conf["AMPWEBADDRESS"])
{
	out("Please update your modules and reload Asterisk by visiting http://".$amp_conf["AMPWEBADDRESS"]."/admin",false);
}
else
{
	out("Please update your modules and reload Asterisk by browsing to your server.",false);
}

out("",false);
out("*************************************************************************",false);
out("* Note: It's possible that if you click the red 'Update Now' bar BEFORE *",false);
out("* updating your modules, your machine will start dropping calls. Ensure *",false);
out("* that all modules are up to date BEFORE YOU CLICK THE RED BAR. As long *",false);
out("* as this is observed, your machine will be fully functional whilst the *",false);
out("* upgrade is in progress.                                               *",false);
out("*************************************************************************",false);
// vim: set ts=4 sw=4 : //
// Ensure you 'set modeline' in your ~/.vimrc to activate this //
?>
